home *** CD-ROM | disk | FTP | other *** search
- (*===========================================================================*)
- (* Authentication tasks *)
- (* *)
- (* Copyright 1991 by H. Roy Engehausen. All rights reserved. *)
- (* This software may be freely distributed and used, but it may not *)
- (* under any circumstances be sold by anyone other than the author. *)
- (* It may be distributed by a commercial company as long as it is *)
- (* for no cost. *)
- (* *)
- (*===========================================================================*)
-
- {$UNDEF DEBUG_PASS}
- {$UNDEF DEBUG_FILE} (* Debug checking the file for a password *)
-
- {$O+}
-
- UNIT BBAUTH;
-
- INTERFACE
-
- PROCEDURE user_auth(work_1 : STRING);
-
- IMPLEMENTATION
-
- USES
- CRT,
- DOS,
- bbdummy,
- bbmdata,
- bbmess,
- bbmisc,
- bbmisc5,
- bbrdata,
- bbsdata,
- bbstr,
- match;
-
- PROCEDURE user_auth(work_1 : STRING);
-
- CONST
- no_of_no = 5; (* Number of letters in the challenge *)
-
- VAR
- b : BOOLEAN;
- i : INTEGER;
- j : BYTE;
- k : BYTE;
- num_list : ARRAY[1..no_of_no] OF BYTE;
- pw_file : TEXT;
- pw_ok : BOOLEAN;
- work_2 : STRING[8];
-
- LABEL
- iterate_i, loop_iterate, loop_leave;
-
- BEGIN;
-
- (*-----------------------------------------------------------------------*)
- (* See if the password file exists. If not, we can't authenticate *)
- (*-----------------------------------------------------------------------*)
-
- IF opt_block.passwd_fn = '' THEN
- BEGIN;
- send_tnc_data_str('No password file specified' + cr);
- active_tcb^.error_sw := TRUE;
- active_tcb^.tcb_error_reason := 255; (* Suppress message *)
- EXIT;
- END;
-
- (*-----------------------------------------------------------------------*)
- (* Open file for input and handle errors *)
- (*-----------------------------------------------------------------------*)
-
- ASSIGN(pw_file, opt_block.passwd_fn);
-
- {$I-}
- RESET(pw_file);
- {$I+}
-
- i := IORESULT;
-
- IF i <> 0 THEN
- BEGIN;
- send_tnc_data_str('Cannot open password file' + cr);
- send_tnc_data_str(dos_err_message(i) + cr);
- active_tcb^.error_sw := TRUE;
- active_tcb^.tcb_error_reason := 255; (* Suppress message *)
- EXIT;
- END;
-
- (*-----------------------------------------------------------------------*)
- (* Loop here looking for the right line in the file *)
- (*-----------------------------------------------------------------------*)
-
- loop_iterate:
-
- (*-----------------------------------------------------------------------*)
- (* If we have reached the end then leave with a blank line *)
- (*-----------------------------------------------------------------------*)
-
- IF EOF(pw_file) THEN
- BEGIN;
- work_1 := '';
- GOTO loop_leave;
- END;
-
- (*-----------------------------------------------------------------------*)
- (* Read a line from the file *)
- (*-----------------------------------------------------------------------*)
-
- READLN(pw_file, work_1);
-
- (*-----------------------------------------------------------------------*)
- (* Parse the link and ignore comments *)
- (*-----------------------------------------------------------------------*)
-
- upcase_str_var(work_1);
- strip_var(work_1, 'B');
-
- IF (work_1 = '') OR (work_1[1] = ';') OR (WORDS(work_1) < 2) THEN
- GOTO loop_iterate;
-
- (*-----------------------------------------------------------------------*)
- (* Get userid *)
- (*-----------------------------------------------------------------------*)
-
- work_2 := subword(@work_1, 1, 1);
-
- (*-----------------------------------------------------------------------*)
- (* See if this is the right user. If not, try next line *)
- (*-----------------------------------------------------------------------*)
-
- {$IFDEF DEBUG_FILE}
- WRITELN('Test -- ', active_tcb^.uid_data.user_id, '/', work_2,
- ' -- ', match_str(active_tcb^.uid_data.user_id, work_2));
- {$ENDIF}
-
- IF NOT match_str(active_tcb^.uid_data.user_id, work_2) THEN
- GOTO loop_iterate;
-
- (*-----------------------------------------------------------------------*)
- (* Get the password. We skip the userid and get the rest. Don't use *)
- (* subword because of multiple blank suppression *)
- (*-----------------------------------------------------------------------*)
-
- i := 1;
-
- WHILE work_1[i] <> ' ' DO
- INC(i);
-
- REPEAT
- INC(i);
- UNTIL work_1[i] <> ' ';
-
- work_1 := COPY(work_1, i, 255);
-
- {$IFDEF DEBUG_FILE}
- WRITELN('pw = ', LENGTH(work_1), ' -- "', work_1, '"');
- {$ENDIF}
-
- (*-----------------------------------------------------------------------*)
- (* Come here when we have either found the right line or ran off the *)
- (* end of the file *)
- (*-----------------------------------------------------------------------*)
-
- loop_leave:
-
- (*-----------------------------------------------------------------------*)
- (* Close the file *)
- (*-----------------------------------------------------------------------*)
-
- CLOSE(pw_file);
-
- (*-----------------------------------------------------------------------*)
- (* If we didn't find the user then we are sick *)
- (*-----------------------------------------------------------------------*)
-
- IF work_1 = '' THEN
- BEGIN;
- send_tnc_data_str('Password file does not contain record for user '
- + active_tcb^.uid_data.user_id
- + cr);
- active_tcb^.error_sw := TRUE;
- active_tcb^.tcb_error_reason := 255; (* Suppress message *)
- EXIT;
- END;
-
- (*-----------------------------------------------------------------------*)
- (* Passowrd is too short *)
- (*-----------------------------------------------------------------------*)
-
- IF LENGTH(work_1) < (no_of_no + 2) THEN
- BEGIN;
- send_tnc_data_str('Password is too short for user '
- + active_tcb^.uid_data.user_id
- + cr);
- active_tcb^.error_sw := TRUE;
- active_tcb^.tcb_error_reason := 255; (* Suppress message *)
- EXIT;
- END;
-
- (*-----------------------------------------------------------------------*)
- (* Get ready to match the password *)
- (*-----------------------------------------------------------------------*)
-
- pw_ok := FALSE;
-
- (*-----------------------------------------------------------------------*)
- (* Loop until user is done *)
- (*-----------------------------------------------------------------------*)
-
- REPEAT
-
- (*---------------------------------------------------------------------*)
- (* Send the first part of the message *)
- (*---------------------------------------------------------------------*)
-
- send_tnc_data_str(get_message(message_enter_password) + ' --');
-
- (*---------------------------------------------------------------------*)
- (* Get the numbers *)
- (*---------------------------------------------------------------------*)
-
- i := 1;
- REPEAT
-
- (*-------------------------------------------------------------------*)
- (* Make sure we don't point to a blank *)
- (*-------------------------------------------------------------------*)
-
- REPEAT
- j := RANDOM(LENGTH(work_1)) + 1;
- UNTIL work_1[j] <> ' ';
-
- (*-------------------------------------------------------------------*)
- (* Make sure we don't have a duplicate *)
- (*-------------------------------------------------------------------*)
-
- FOR k := 1 TO i-1 DO
- IF j = num_list[k] THEN
- GOTO iterate_i;
-
- (*-------------------------------------------------------------------*)
- (* OK.. Got a number. Store it away *)
- (*-------------------------------------------------------------------*)
-
- num_list[i] := j;
-
- INC(i);
-
- (*-------------------------------------------------------------------*)
- (* Come here to repeat the loop *)
- (*-------------------------------------------------------------------*)
-
- iterate_i:
-
- UNTIL i > no_of_no;
-
- (*---------------------------------------------------------------------*)
- (* Sort the numbers into ascending order *)
- (*---------------------------------------------------------------------*)
-
- i := 1;
- REPEAT
- IF num_list[i] > num_list[i+1] THEN
- BEGIN;
-
- j := num_list[i];
- num_list[i] := num_list[i+1];
- num_list[i+1] := j;
-
- i := 0;
- END;
- INC(i);
- UNTIL i = no_of_no;
-
- (*---------------------------------------------------------------------*)
- (* Put the numbers in character format and send to user *)
- (*---------------------------------------------------------------------*)
-
- FOR i := 1 TO no_of_no DO
- BEGIN;
- STR(num_list[i], work_2);
- send_tnc_data_str(' ' + work_2);
- END;
-
- send_tnc_data_str(cr);
-
- (*---------------------------------------------------------------------*)
- (* Get response *)
- (*---------------------------------------------------------------------*)
-
- REPEAT
-
- work_2 := read_tnc_data_str;
-
- strip_crlf(work_2);
- upcase_str_var(work_2);
-
- IF work_2 = '?' THEN
- IF pw_ok THEN
- send_message(message_auth_complete)
- ELSE
- send_message(message_auth_incomplete);
-
- UNTIL work_2 <> '?';
-
- {$IFDEF DEBUG_PASS}
- WRITELN('Passin=', LENGTH(work_2), '=', work_2);
- {$ENDIF}
-
- (*---------------------------------------------------------------------*)
- (* Test the response *)
- (*---------------------------------------------------------------------*)
-
- b := FALSE;
-
- IF LENGTH(work_2) = no_of_no THEN
- BEGIN;
-
- b := TRUE;
-
- FOR i := 1 TO no_of_no DO
- BEGIN;
- b := b AND (work_2[i] = work_1[num_list[i]]);
- {$IFDEF DEBUG_PASS}
- WRITELN('B = ', b, ' -- i = ', i,
- ' -- ', work_2[i],
- ' -- ', num_list[i], work_1[num_list[i]]);
- {$ENDIF}
- END;
-
- END;
-
- {$IFDEF DEBUG_PASS}
- WRITELN('B = ', b, ' -- ok = ', pw_ok);
- {$ENDIF}
-
- (*---------------------------------------------------------------------*)
- (* If this was good then turn on password switch *)
- (*---------------------------------------------------------------------*)
-
- IF b THEN
- pw_ok := TRUE;
-
- UNTIL work_2 = ''; (*---- Loop until user sends blank line --------------*)
-
- (*-----------------------------------------------------------------------*)
- (* See the error switch accordingly *)
- (*-----------------------------------------------------------------------*)
-
- IF pw_ok THEN
- EXIT;
-
- active_tcb^.error_sw := TRUE;
- active_tcb^.tcb_error_reason := 1; (* Authentication failed *)
-
- END;
-
- END.